import { GameEvent, SysOrder } from "../../GameDef";
import { Rect } from "../../lib/kgame/d2/math/Rect";
import { Vec2 } from "../../lib/kgame/d2/math/Vec2";
import { ECSEntity } from "../../lib/kgame/ecs/ECSEntity";
import { IECSFilter } from "../../lib/kgame/ecs/ECSFilter";
import { ECSSys } from "../../lib/kgame/ecs/ECSSys";
import { CmpSnake } from "../cmp/CmpSnake";
import { SnakeFactory } from "../factory/SnakeFactory";
import { SCmpWorld } from "../scmp/SCmpWorld";

const spawnPos = new Vec2();
const spawnRect = new Rect();

/**
 * 蛇系统
 */
export class SysSnake extends ECSSys {

    world: SCmpWorld;

    get updateOrder(): number {
        return SysOrder.snake;
    }

    get ifilter(): IECSFilter {
        return { includeAll: [CmpSnake] };
    }

    protected onStart(): void {
        this.world = this.scene.getCmp(SCmpWorld);
    }

    onDestroy(): void {
        this.world = null;
    }

    protected onUpdateEntity(entity: ECSEntity): void {
        const snake = entity.getCmp(CmpSnake);

        //检测蛇移除
        if (snake.doRemove) {
            if (!snake.head) {
                snake.doRemove = false;
                snake.entity.removeSelf();
                this.scene.send(GameEvent.snakeRemove, snake.snakeId);
            }
            return;
        }

        //检测蛇复活
        if (snake.death) {
            snake.respawnCd -= this.scene.dt;
            if (snake.respawnCd <= 0) {
                //复活
                const { initLen, initSize } = XSnakeMisc;
                const wrold = this.scene.getCmp(SCmpWorld);
                const safeDis = initSize * initLen + 25;

                //优先从四叉树从中找出没有蛇的地方
                const snakeTree = this.world.snakeQuadTree;
                const emptyNodes = snakeTree.getEmptyNodes();
                if (emptyNodes.length > 0) {
                    const node = this.scene.rand.choose(emptyNodes);
                    spawnRect.setRectTo(node.rect).intersectionRect(
                        Rect.T.setRect(
                            wrold.rect.x + safeDis,
                            wrold.rect.y + safeDis,
                            wrold.rect.width - safeDis,
                            wrold.rect.height - safeDis
                        ));
                    spawnPos.setPos(
                        spawnRect.x + this.scene.rand.rand() * spawnRect.width,
                        spawnRect.y + this.scene.rand.rand() * spawnRect.height
                    );
                } else {
                    wrold.getRandPos(safeDis, spawnPos);
                }

                snake.pos.setPosTo(spawnPos);
                snake.trans.rot = this.scene.rand.randRad();
                const head = snake.head = SnakeFactory.createHead(snake);
                for (let i = 0; i < initLen; ++i) {
                    SnakeFactory.createBody(head, spawnPos.moveRad(snake.trans.rot, -head.space * i));
                }
                this.scene.send(GameEvent.snakeSpawn, snake);
            }
        }
    }

}


declare global {

    interface ECSEventData {
        [GameEvent.snakeSpawn]: CmpSnake,
        [GameEvent.snakeDead]: CmpSnake
        [GameEvent.snakeGhost]: CmpSnake
    }

}